package com.tucanstubs.android_wheresmystuff.database;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.StringTokenizer;

import com.tucanstubs.android_wheresmystuff.items.Donation;
import com.tucanstubs.android_wheresmystuff.items.FoundItem;
import com.tucanstubs.android_wheresmystuff.items.Item;
import com.tucanstubs.android_wheresmystuff.items.ItemType;
import com.tucanstubs.android_wheresmystuff.items.LostItem;
import com.tucanstubs.android_wheresmystuff.items.Request;
import com.tucanstubs.android_wheresmystuff.login.User;

import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.util.Log;
/**
 * Class that holds all the static methods pertaining to the 
 * Items table. 
 * @author Group 37
 * @version 2.0 4/12/2013
 */
public class ItemHelper{
	private static SQLiteOpenHelper dbhelper;
	private static SQLiteDatabase database;
	
	private static final String TAG = "ITEMHELPER";
	/**
	 * Open a writable database instance. Also refresh the current 
	 * DatabaseOperator instance if it is null;
	 * @param context The current running Activity
	 */
	private static void open(Context context){
		if(dbhelper == null)
			dbhelper = DatabaseOperator.getInstance(context);
		database = dbhelper.getWritableDatabase();
	}
	/**
	 * Add an Item to the database and match it to the given user 
	 * object. If the item exists in the database update its entry
	 * @param context The current running Activity
	 * @param item The item to be added or updated
	 * @param user The user associated with that item
	 */
	public static void addItem(Context context,Item item,User user){
		ContentValues values = new ContentValues();
		Log.i(TAG,"ID: " + item.getId());
		values.put(DatabaseOperator.ITEM_ID,item.getId());
		values.put(DatabaseOperator.USER_ID,user.getUserName());
		values.put(DatabaseOperator.NAME_COLUMN,item.getName());
		values.put(DatabaseOperator.DESCRIPTION_COLUMN,item.getDescription());
		double[] loc = item.getLocation();
		values.put(DatabaseOperator.LOCATION_COLUMN,loc[0] + " " + loc[1]);
		if(item.isMatchedUp())
			values.put(DatabaseOperator.MATCHED_COLUMN,1);
		else
			values.put(DatabaseOperator.MATCHED_COLUMN,0);
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		values.put(DatabaseOperator.DATE_COLUMN,format.format(item.getDateEntered()));
		if(item instanceof FoundItem)
			values.put(DatabaseOperator.ITEMTYPE_COLUMN,((FoundItem)item).getItemType().name());
		else
			values.put(DatabaseOperator.ITEMTYPE_COLUMN,"");
		if(item instanceof LostItem){
			values.put(DatabaseOperator.REWARD_COLUMN,((LostItem)item).getReward());
			Log.i(TAG,((LostItem)item).getItemType().name());
			String type = ((LostItem)item).getItemType().name();
			values.put(DatabaseOperator.ITEMTYPE_COLUMN,type);
		}else
			values.put(DatabaseOperator.REWARD_COLUMN,-1.0);
		values.put(DatabaseOperator.TYPE_ID,item.getClass().getSimpleName());
		if(getItem(context,item.getId()) == null){
			open(context);
			database.insert(DatabaseOperator.ITEM_TABLE_NAME,null,values);
		}else {
			open(context);
			database.update(DatabaseOperator.ITEM_TABLE_NAME,values
					,DatabaseOperator.ITEM_ID +"="+item.getId(),null);
		}
		database.close();
	}
	/**
	 * Set the matched status of the given item (specified by item id)
	 * @param context The current running Activity
	 * @param matched The matched status of the given item
	 * @param id The item id of the given item
	 */
	public static void setMatched(Context context,boolean matched,int id){
		ContentValues values = new ContentValues();
		if(matched)
			values.put(DatabaseOperator.MATCHED_COLUMN,1);
		else
			values.put(DatabaseOperator.MATCHED_COLUMN,0);
		open(context);
		database.update(DatabaseOperator.ITEM_TABLE_NAME,values
				,DatabaseOperator.ITEM_ID +"="+id,null);
		database.close();
	}
	/**
	 * Get the next available item id in the database (caluclated as the MAX(item id) + 1)
	 * @param context The current running Activity
	 * @return The next available item id
	 */
	public static int getNextId(Context context){
		open(context);
		String query = "SELECT MAX(" + DatabaseOperator.ITEM_ID + ") FROM " + DatabaseOperator.ITEM_TABLE_NAME;
		Cursor cursor = database.rawQuery(query,null);
		cursor.moveToFirst();
		int ret = cursor.getInt(0);
		cursor.close();
		database.close();
		return ret+1;
	}
	/**
	 * Get an item based on its id
	 * @param context The current running ACtivity
	 * @param id The item id of the item to be got
	 * @return The item if it exists in the database else null
	 */
	public static Item getItem(Context context,int id){
		open(context);
		String query = "Select * FROM " + DatabaseOperator.ITEM_TABLE_NAME 
				+ " WHERE " + DatabaseOperator.ITEM_ID + "=" + id;
		Cursor cursor = database.rawQuery(query,null);
		if(cursor.getCount() != 1){
			return null;
		}
		cursor.moveToFirst();
		Item ret = cursorToItem(cursor);
		cursor.close();
		database.close();
		return ret;
	}
	/**
	 * Gets all the items associated with the given user userName
	 * and returns them as an ArrayList
	 * @param context The current running Activity
	 * @param userName The userName we need to lookup by
	 * @return An arrayList of items that are associated with the given user
	 */
	public static ArrayList<Item> getItems(Context context,String userName){
		open(context);
		ArrayList<Item> list = new ArrayList<Item>();
		String query = "Select * FROM " + DatabaseOperator.ITEM_TABLE_NAME 
				+ " WHERE " + DatabaseOperator.USER_ID + "=" +"'" +userName + "'";
		Cursor cursor = database.rawQuery(query,null);
		cursor.moveToFirst();
		while(!cursor.isAfterLast()){
			list.add(cursorToItem(cursor));
			cursor.moveToNext();
		}
		cursor.close();
		dbhelper.close();
		return list;
	}
	/**
	 * We get instances of the Cursor class from database queries so 
	 * we use cursorToItem to convert the data contained in the cursor
	 * to an item object
	 * @param cursor The current cursor to convert
	 * @return An item object associated with the data in the cursor.
	 */
	public static Item cursorToItem(Cursor cursor){
		Item ret = null;
		StringTokenizer st = new StringTokenizer(cursor.getString(4));
		double[] location = {Double.parseDouble(st.nextToken()), Double.parseDouble(st.nextToken())};
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");
		Date date = null;
		try {
			date = format.parse(cursor.getString(6));
		} catch (ParseException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		String type = cursor.getString(9);
		if(type.equals("Donation"))
			ret = new Donation(cursor.getString(2),cursor.getString(3),location,date,cursor.getInt(0));
		else if(type.equals("FoundItem")){
			String t = cursor.getString(8);
			if(t.equals("KEEPSAKE"))
				ret = new FoundItem(cursor.getString(2),cursor.getString(3),location,
						date,ItemType.KEEPSAKE,cursor.getInt(0));
			else if(t.equals("HEIRLOOM"))
				ret = new FoundItem(cursor.getString(2),cursor.getString(3),location,
						date,ItemType.HEIRLOOM,cursor.getInt(0));
			else if(t.equals("MISC"))
				ret = new FoundItem(cursor.getString(2),cursor.getString(3),location,
						date,ItemType.MISC,cursor.getInt(0));
		}else if(type.equals("LostItem")){
			String t = cursor.getString(8);
			if(t.equals("KEEPSAKE"))
				ret = new LostItem(cursor.getString(2),cursor.getString(3),location,
						date,cursor.getDouble(7),ItemType.KEEPSAKE,cursor.getInt(0));
			else if(t.equals("HEIRLOOM"))
				ret = new LostItem(cursor.getString(2),cursor.getString(3),location,
						date,cursor.getDouble(7),ItemType.HEIRLOOM,cursor.getInt(0));
			else if(t.equals("MISC"))
				ret = new LostItem(cursor.getString(2),cursor.getString(3),location,
						date,cursor.getDouble(7),ItemType.MISC,cursor.getInt(0));
		}else if(type.equals("Request")){
			ret = new Request(cursor.getString(2),cursor.getString(3),location,date,cursor.getInt(0));
		}
		if(cursor.getInt(5) == 1){
			ret.setMatchedUp(true);
		} else {
			ret.setMatchedUp(false);
		}
		Log.i(TAG,"isMatched: " + ret.isMatchedUp());
		return ret;
	}
}
